﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
using System.Drawing;
using OpenTK.Graphics;
using Common;

namespace T18_Billboards {
    class T18_BillboardsGameWindow : GameWindow {
        public T18_BillboardsGameWindow() {
            this.Load += T18_BillboardsGameWindow_Load;
            this.Resize += T18_BillboardsGameWindow_Resize;
            this.RenderFrame += T18_BillboardsGameWindow_RenderFrame;
            this.Unload += T18_BillboardsGameWindow_Unload;
            this.Width = 1024;
            this.Height = 768;
            this.Title = "T18_BillboardsGameWindow";

        }


        private void T18_BillboardsGameWindow_RenderFrame(object sender, FrameEventArgs e) {
            GL.ClearColor(.1f, .1f, .99f, .9f);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            Render();

            SwapBuffers();
            ProcessEvents();
        }

        Vao vao;
        Shader shader, cubeShader;
        Texture2D texture;
        float[]  vertexBufferData= {
             -0.5f, -0.5f, 0.0f,
          0.5f, -0.5f, 0.0f,
         -0.5f,  0.5f, 0.0f,
          0.5f,  0.5f, 0.0f,
        };
        Vbo<float> billboardVbo;
        ModelMesh cubeMesh;
        float[] cubeVertexBufferData = { -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f };
        float[] cubeColorBufferData = { 0.583f, 0.771f, 0.014f, 0.609f, 0.115f, 0.436f, 0.327f, 0.483f, 0.844f, 0.822f, 0.569f, 0.201f, 0.435f, 0.602f, 0.223f, 0.310f, 0.747f, 0.185f, 0.597f, 0.770f, 0.761f, 0.559f, 0.436f, 0.730f, 0.359f, 0.583f, 0.152f, 0.483f, 0.596f, 0.789f, 0.559f, 0.861f, 0.639f, 0.195f, 0.548f, 0.859f, 0.014f, 0.184f, 0.576f, 0.771f, 0.328f, 0.970f, 0.406f, 0.615f, 0.116f, 0.676f, 0.977f, 0.133f, 0.971f, 0.572f, 0.833f, 0.140f, 0.616f, 0.489f, 0.997f, 0.513f, 0.064f, 0.945f, 0.719f, 0.592f, 0.543f, 0.021f, 0.978f, 0.279f, 0.317f, 0.505f, 0.167f, 0.620f, 0.077f, 0.347f, 0.857f, 0.137f, 0.055f, 0.953f, 0.042f, 0.714f, 0.505f, 0.345f, 0.783f, 0.290f, 0.734f, 0.722f, 0.645f, 0.174f, 0.302f, 0.455f, 0.848f, 0.225f, 0.587f, 0.040f, 0.517f, 0.713f, 0.338f, 0.053f, 0.959f, 0.120f, 0.393f, 0.621f, 0.362f, 0.673f, 0.211f, 0.457f, 0.820f, 0.883f, 0.371f, 0.982f, 0.099f, 0.879f };
        VertexAttribManager cubeAttribs = new VertexAttribManager();
        VertexAttribManager billboardAttribs = new VertexAttribManager();
        private void T18_BillboardsGameWindow_Load(object sender, EventArgs e) {

            VSync = VSyncMode.Off;
            GL.Enable(EnableCap.DepthTest);
            GL.DepthFunc(DepthFunction.Less);

            vao = new Vao();
            shader = new Shader("shader.vs", "shader.fs");
            texture = Texture2D.Load("ExampleBillboard.dds");
            billboardVbo = new Vbo<float>(vertexBufferData);
            billboardAttribs.AddAttrib(3, billboardVbo);
            cubeShader = new Shader("TransformVertexShader.vertexshader", "ColorFragmentShader.fragmentshader");
            cubeMesh = new ModelMesh();
            cubeMesh.Vertices = GLUtility.ToVector3Array(cubeVertexBufferData);
            cubeMesh.Normals = GLUtility.ToVector3Array(cubeColorBufferData);
            cubeMesh.VertexBuffer = new Vbo<Vector3>(BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw, cubeMesh.Vertices);
            cubeMesh.NormalBuffer = new Vbo<Vector3>(BufferTarget.ArrayBuffer, BufferUsageHint.DynamicDraw, cubeMesh.Normals);
            cubeAttribs.AddAttrib(3, cubeMesh.VertexBuffer);
            cubeAttribs.AddAttrib(3, cubeMesh.NormalBuffer);
        }

        private void Render() {
            InputControls.computeMatricesFromInput(this);
            GL.Disable(EnableCap.Blend);
            cubeShader.Use();
            var cubeModel = Matrix4.Identity;
            var scale = Matrix4.CreateScale(.2f, .2f, .2f);
            cubeModel = cubeModel * scale;
            var view = InputControls.ViewMatrix;
            var projection = InputControls.ProjectionMatrix;
            var cubeMvp = cubeModel * view * projection;
            cubeShader.SetMatrix4("MVP", ref cubeMvp);
            cubeAttribs.Enable();
            GL.DrawArrays(PrimitiveType.Triangles, 0, cubeMesh.Vertices.Length);
            cubeAttribs.Disable();

            Vector3 cameraPosition = view.Inverted().Row3.Xyz;
            var viewProjection = view * projection;

            GL.Enable(EnableCap.Blend);
            GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
            shader.Use();
            texture.Active(TextureUnit.Texture0, shader, "myTextureSampler");

            shader.SetVector3("CameraRight_worldspace", view.Column0.Xyz);
            shader.SetVector3("CameraUp_worldspace", view.Column1.Xyz);
            shader.SetVector3("BillboardPos",0f,.5f,0f);
            shader.SetVector2("BillboardSize",1.0f,0.125f);

            float lifeLevel = (float)Math.Sin(InputControls.getTime()) * 0.1f + 0.7f;
            shader.SetFloat("LifeLevel", lifeLevel);
            shader.SetMatrix4("VP", viewProjection);

            billboardAttribs.Enable();
            billboardVbo.Bind();
            GL.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
            billboardAttribs.Disable();


        }

        private void T18_BillboardsGameWindow_Resize(object sender, EventArgs e) {
            GL.Viewport(0, 0, Width, Height);
        }



        private void T18_BillboardsGameWindow_Unload(object sender, EventArgs e) {
            GlDisposableObjectBase.DisposeObjects(vao, shader,texture,cubeShader,billboardVbo,cubeMesh);
        }

    }
}
